﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;

namespace DevOnServer
{
    public class CNetConnection : IDisposable
    {
        public bool Connected;

        public bool Free;

        public Socket Socket;

        public int Port;

        public void Dispose()
        {
            close();
        }

        public void close()
        {
            if (Connected)
            {
                Socket.Close();
                Socket = null;
                Connected = false;
            }
        }
    }

    public class CNetAcceptor : CNetConnection
    {
        public bool bind(int port)
        {
            Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            Port = port;

            try
            {
                Socket.Bind(new IPEndPoint(IPAddress.Any, port));
                Socket.Listen(64);
                Connected = true;
            }
            catch (Exception e)
            {
                CConsole.WriteLine("Acceptor bind socket error: {0}", e.Message);
                Connected = false;
            }

            return Connected;
        }

        public Queue<CNetClient> NewClients = new Queue<CNetClient>();
    }

    public class CNetClient : CNetConnection
    {
        public bool send(CPacket packet)
        {
            int count = packet.Lenght;
            byte[] data = packet.Data;
            int sendBytes = 0;
            int rc = 0;

            try
            {
                while (sendBytes < count)
                {
                    rc = Socket.Send(data, sendBytes, count - sendBytes, SocketFlags.None);

                    if (rc >= 0)
                        sendBytes += rc;
                    else
                        return false;
                }
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        private static byte[] s_buffer = new byte[1024];

        public bool receive()
        {
            int received = 0;

            while (true)
            {
                try
                {
                    received = Socket.Receive(s_buffer, 1024, SocketFlags.None);
                }
                catch (Exception)
                {
                    return false;
                }

                if (received <= 0)
                    return false;

                Incomming.addBytes(s_buffer, received);

                if (received != 1024)
                    break;
            }

            return true;
        }

        public CPacket Incomming = new CPacket();

        public string IP;
    }

    public class CNetConnector : CNetClient
    {
        public bool connect(string ip, int port, int retries = 0)
        {
            Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            Port = port;
            IP = ip;

            try
            {
                Socket.Connect(new IPEndPoint(IPAddress.Parse(ip), port));
                Connected = true;
            }
            catch (Exception e)
            {
                CConsole.WriteLine("Connector connect socket error: {0}", e.Message);
                Connected = false;
            }

            return Connected;
        }
    }
}